home *** CD-ROM | disk | FTP | other *** search
/ STraTOS 1997 April & May / STraTOS 1 - 1997 April & May.iso / CD01 / LINUX / MATH_EMU.ZIP / MATH_EMU / FPU_EXPL.C < prev    next >
Encoding:
C/C++ Source or Header  |  1979-12-31  |  9.5 KB  |  276 lines

  1. /*        $NetBSD: fpu_explode.c,v 1.2 1994/11/20 20:52:41 deraadt Exp $ */
  2.  
  3. /*
  4.  * Copyright (c) 1992, 1993
  5.  *        The Regents of the University of California.  All rights reserved.
  6.  *
  7.  * This software was developed by the Computer Systems Engineering group
  8.  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
  9.  * contributed to Berkeley.
  10.  *
  11.  * All advertising materials mentioning features or use of this software
  12.  * must display the following acknowledgement:
  13.  *        This product includes software developed by the University of
  14.  *        California, Lawrence Berkeley Laboratory.
  15.  *
  16.  * Redistribution and use in source and binary forms, with or without
  17.  * modification, are permitted provided that the following conditions
  18.  * are met:
  19.  * 1. Redistributions of source code must retain the above copyright
  20.  *    notice, this list of conditions and the following disclaimer.
  21.  * 2. Redistributions in binary form must reproduce the above copyright
  22.  *    notice, this list of conditions and the following disclaimer in the
  23.  *    documentation and/or other materials provided with the distribution.
  24.  * 3. All advertising materials mentioning features or use of this software
  25.  *    must display the following acknowledgement:
  26.  *        This product includes software developed by the University of
  27.  *        California, Berkeley and its contributors.
  28.  * 4. Neither the name of the University nor the names of its contributors
  29.  *    may be used to endorse or promote products derived from this software
  30.  *    without specific prior written permission.
  31.  *
  32.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  33.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  34.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  35.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  36.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  37.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  38.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  39.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  40.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  41.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  42.  * SUCH DAMAGE.
  43.  *
  44.  *        @(#)fpu_explode.c   8.1 (Berkeley) 6/11/93
  45.  */
  46.  
  47. /*
  48.  * FPU subroutines: `explode' the machine's `packed binary' format numbers
  49.  * into our internal format.
  50.  */
  51.  
  52. #include "types.h"
  53.  
  54. #include "ieee.h"
  55. #include "reg.h"
  56.  
  57. #include "fpu_arit.h"
  58. #include "fpu_emul.h"
  59.  
  60.  
  61. /* Conversion to internal format -- note asymmetry. */
  62. static int          fpu_itof __P((struct fpn *fp, u_int i));
  63. static int          fpu_stof __P((struct fpn *fp, u_int i));
  64. static int          fpu_dtof __P((struct fpn *fp, u_int i, u_int j));
  65. static int          fpu_xtof __P((struct fpn *fp, u_int i, u_int j, u_int k));
  66.  
  67. /*
  68.  * N.B.: in all of the following, we assume the FP format is
  69.  *
  70.  *        ---------------------------
  71.  *        | s | exponent | fraction |
  72.  *        ---------------------------
  73.  *
  74.  * (which represents -1**s * 1.fraction * 2**exponent), so that the
  75.  * sign bit is way at the top (bit 31), the exponent is next, and
  76.  * then the remaining bits mark the fraction.  A zero exponent means
  77.  * zero or denormalized (0.fraction rather than 1.fraction), and the
  78.  * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
  79.  *
  80.  * Since the sign bit is always the topmost bit---this holds even for
  81.  * integers---we set that outside all the *tof functions.  Each function
  82.  * returns the class code for the new number (but note that we use
  83.  * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
  84.  */
  85.  
  86. /*
  87.  * int -> fpn.
  88.  */
  89. static int
  90. fpu_itof(fp, i)
  91.           register struct fpn *fp;
  92.           register u_int i;
  93. {
  94.  
  95.           if (i == 0)
  96.                     return (FPC_ZERO);
  97.           /*
  98.            * The value FP_1 represents 2^FP_LG, so set the exponent
  99.            * there and let normalization fix it up.  Convert negative
  100.            * numbers to sign-and-magnitude.  Note that this relies on
  101.            * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
  102.            */
  103.           fp->fp_exp = FP_LG;
  104.           fp->fp_mant[0] = (int)i < 0 ? -i : i;
  105.           fp->fp_mant[1] = 0;
  106.           fp->fp_mant[2] = 0;
  107.           fp->fp_mant[3] = 0;
  108.           fpu_norm(fp);
  109.           return (FPC_NUM);
  110. }
  111.  
  112. #define   mask(nbits) ((1 << (nbits)) - 1)
  113.  
  114. /*
  115.  * All external floating formats convert to internal in the same manner,
  116.  * as defined here.  Note that only normals get an implied 1.0 inserted.
  117.  */
  118. #define   FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
  119.     if (exp == 0) { if (allfrac == 0) return (FPC_ZERO); \
  120.     fp->fp_exp = 1 - expbias; fp->fp_mant[0] = f0; \
  121.     fp->fp_mant[1] = f1; fp->fp_mant[2] = f2; fp->fp_mant[3] = f3; \
  122.     fpu_norm(fp); return (FPC_NUM); } \
  123.     if (exp == (2 * expbias + 1)) { if (allfrac == 0) return (FPC_INF); \
  124.     fp->fp_mant[0] = f0; fp->fp_mant[1] = f1; \
  125.     fp->fp_mant[2] = f2; fp->fp_mant[3] = f3; return (FPC_QNAN); } \
  126.      fp->fp_exp = exp - expbias; fp->fp_mant[0] = FP_1 | f0; \
  127.     fp->fp_mant[1] = f1; fp->fp_mant[2] = f2; fp->fp_mant[3] = f3; \
  128.     return (FPC_NUM)
  129.  
  130. /*
  131.  * 32-bit single precision -> fpn.
  132.  * We assume a single occupies at most (64-FP_LG) bits in the internal
  133.  * format: i.e., needs at most fp_mant[0] and fp_mant[1].
  134.  */
  135. static int
  136. fpu_stof(fp, i)
  137.           register struct fpn *fp;
  138.           register u_int i;
  139. {
  140.           register int exp;
  141.           register u_int frac, f0, f1;
  142. #define SNG_SHIFT (SNG_FRACBITS - FP_LG)
  143.  
  144.           exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
  145.           frac = i & mask(SNG_FRACBITS);
  146.           f0 = frac >> SNG_SHIFT;
  147.           f1 = frac << (32 - SNG_SHIFT);
  148.           FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
  149. }
  150.  
  151. /*
  152.  * 64-bit double -> fpn.
  153.  * We assume this uses at most (96-FP_LG) bits.
  154.  */
  155. static int
  156. fpu_dtof(fp, i, j)
  157.           register struct fpn *fp;
  158.           register u_int i, j;
  159. {
  160.           register int exp;
  161.           register u_int frac, f0, f1, f2;
  162. #define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
  163.  
  164.           exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
  165.           frac = i & mask(DBL_FRACBITS - 32);
  166.           f0 = frac >> DBL_SHIFT;
  167.           f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
  168.           f2 = j << (32 - DBL_SHIFT);
  169.           frac |= j;
  170.           FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
  171. }
  172.  
  173. /*
  174.  * 96-bit extended -> fpn.
  175.  */
  176. static int
  177. fpu_xtof(fp, i, j, k)
  178.           register struct fpn *fp;
  179.           register u_int i, j, k;
  180. {
  181.           register int exp;
  182.           register u_int frac, f0, f1, f2;
  183. #define EXT_SHIFT (EXT_FRACBITS - 1 - 32 - FP_LG)
  184.  
  185.           exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS);
  186.           f0 = j >> EXT_SHIFT;
  187.           f1 = (j << (32 - EXT_SHIFT)) | (k >> EXT_SHIFT);
  188.           f2 = k << (32 - EXT_SHIFT);
  189.           frac = j | k;
  190.  
  191.           /* m68k extended does not imply denormal by exp==0 */
  192.           if (exp == 0) {
  193.                     if (frac == 0)
  194.                               return (FPC_ZERO);
  195.                     fp->fp_exp = - EXT_EXP_BIAS;
  196.                     fp->fp_mant[0] = f0;
  197.                     fp->fp_mant[1] = f1;
  198.                     fp->fp_mant[2] = f2;
  199.                     fp->fp_mant[3] = 0;
  200.                     fpu_norm(fp);
  201.                     return (FPC_NUM);
  202.           }
  203.           if (exp == (2 * EXT_EXP_BIAS + 1)) {
  204.                     if (frac == 0)
  205.                               return (FPC_INF);
  206.                     fp->fp_mant[0] = f0;
  207.                     fp->fp_mant[1] = f1;
  208.                     fp->fp_mant[2] = f2;
  209.                     fp->fp_mant[3] = 0;
  210.                     return (FPC_QNAN);
  211.           }
  212.           fp->fp_exp = exp - EXT_EXP_BIAS;
  213.           fp->fp_mant[0] = FP_1 | f0;
  214.           fp->fp_mant[1] = f1;
  215.           fp->fp_mant[2] = f2;
  216.           fp->fp_mant[3] = 0;
  217.           return (FPC_NUM);
  218. }
  219.  
  220. /*
  221.  * Explode the contents of a memory operand.
  222.  */
  223. void
  224. fpu_explode(fe, fp, type, space)
  225.           register struct fpemu *fe;
  226.           register struct fpn *fp;
  227.           int type;
  228.           register u_int *space;
  229. {
  230.           register u_int s;
  231.  
  232.           s = space[0];
  233.           fp->fp_sign = s >> 31;
  234.           fp->fp_sticky = 0;
  235.           switch (type) {
  236.  
  237.           case FTYPE_BYT:
  238.                     s >>= 8;
  239.           case FTYPE_WRD:
  240.                     s >>= 16;
  241.           case FTYPE_LNG:
  242.                     s = fpu_itof(fp, s);
  243.                     break;
  244.  
  245.           case FTYPE_SNG:
  246.                     s = fpu_stof(fp, s);
  247.                     break;
  248.  
  249.           case FTYPE_DBL:
  250.                     s = fpu_dtof(fp, s, space[1]);
  251.                     break;
  252.  
  253.           case FTYPE_EXT:
  254.                     s = fpu_xtof(fp, s, space[1], space[2]);
  255.                     break;
  256.  
  257.           default:
  258. #ifdef DIAGNOSTIC
  259.                    panic("fpu_explode"); 
  260. #endif
  261.           }
  262.           if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
  263.                     /*
  264.                      * Input is a signalling NaN.  All operations that return
  265.                      * an input NaN operand put it through a ``NaN conversion'',
  266.                      * which basically just means ``turn on the quiet bit''.
  267.                      * We do this here so that all NaNs internally look quiet
  268.                      * (we can tell signalling ones by their class).
  269.                      */
  270.                     fp->fp_mant[0] |= FP_QUIETBIT;
  271.                     fe->fe_fpsr |= FPSR_SNAN;     /* assert SNAN exception */
  272.                     s = FPC_SNAN;
  273.           }
  274.           fp->fp_class = s;
  275. }
  276.